#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_actionOuvrir_entr_e_triggered()
{
    QString fileName=QFileDialog::getOpenFileName(this,"Ouvrir un fichier entree","","*.in");
    if(fileName.isEmpty())
        return;
    getIn(fileName.toStdString().c_str(),valEntree,correspondance);
}

void MainWindow::on_actionOuvrir_programme_triggered()
{
  QString fileName=QFileDialog::getOpenFileName(this,"Ouvrir un fichier programme","","*.prog");
  if(fileName.isEmpty())
    return;
  loadProg(fileName.toStdString());
}

void MainWindow::on_actionSuivre_RAM_triggered()
{
  int a=QInputDialog::getInt ( this, "Suivre une addresse RAM", "Adresse", 0,0);  
  ramTracked.push_back(a);
  updateNames();
}

void MainWindow::on_actionSuivre_ROM_triggered()
{ 
  int a= QInputDialog::getInt ( this, "Suivre une addresse ROM", "Adresse", 0,0); 
  romTracked.push_back(a);
  updateNames();
}


void MainWindow::updateNames(){
  int nbElem=sortie.size();

  ui->sortieList->setRowCount(nbElem+ramTracked.size()+romTracked.size());
  ui->sortieList->setHorizontalHeaderItem(0,new QTableWidgetItem("Variable"));
  ui->sortieList->setHorizontalHeaderItem(1,new QTableWidgetItem("Valeur"));
  for(int elem=0;elem<nbElem;elem++){
    ui->sortieList->setItem(elem,0,new QTableWidgetItem(sortie[elem].nom));
    ui->sortieList->setItem(elem,1,new QTableWidgetItem(sortie[elem].values));
  }
  for(int ramElem=nbElem;ramElem<nbElem+ramTracked.size();ramElem++){
    ui->sortieList->setItem(ramElem,0,
			    new QTableWidgetItem(QString("Ram : ")+
						 QString::number(ramTracked[ramElem-nbElem])));
    ui->sortieList->setItem(ramElem,1,new QTableWidgetItem(QString("")));
  }
  for(int romElem=nbElem+ramTracked.size();
      romElem<nbElem+ramTracked.size()+romTracked.size();
      romElem++){
    ui->sortieList->setItem(romElem,0,
			    new QTableWidgetItem(QString("Rom : ")+
						 QString::number(romTracked[romElem-nbElem-ramTracked.size()])));
    ui->sortieList->setItem(romElem,1,new QTableWidgetItem(QString("")));
  }
}

void MainWindow::on_actionOuvrir_triggered()
{

    QString fileName=QFileDialog::getOpenFileName(this,"Ouvrir un fichier circuit compilé","","*.cir");
    if(fileName.isEmpty())
        return;

    ui->sortieList->clear();
    if(vars.empty())
        QObject::connect(&clock,SIGNAL(timeout()),this,SLOT(doStep()));
    first=true;
    vars.clear();
    correspondance.clear();
    entree.clear();
    sortie.clear();
    ramTracked.clear();
    romTracked.clear();
    valEntree.clear();

    clock.stop();
    curStep=0;
    ui->tempsReel->setText("Temps Reel");
    ui->fastest->setText("Vitesse Max");

    if(ReadFile(fileName.toStdString().c_str(), vars,ramTracked,romTracked))
        on_actionOuvrir_entr_e_triggered();


    int nbElem=0;
    int nbEntrees=0;
    for(int var=0;var<(int)vars.size();var++){
      if(vars[var].affichage != nothing && vars[var].fun != IN){
	QString temp(vars[var].name.c_str());
	sortie.push_back(VarState(temp));
	nbElem++;
      }
      if(vars[var].fun == IN){
	QString temp(vars[var].name.c_str());
	entree.push_back(VarState(temp));
	nbEntrees++;
      }
    }

    ui->sortieList->setColumnCount(2);
    ui->sortieList->setRowCount(nbElem+ramTracked.size()+romTracked.size());
    ui->sortieList->setHorizontalHeaderItem(0,new QTableWidgetItem("Variable"));
    ui->sortieList->setHorizontalHeaderItem(1,new QTableWidgetItem("Valeur"));
    for(int elem=0;elem<nbElem;elem++){
      ui->sortieList->setItem(elem,0,new QTableWidgetItem(sortie[elem].nom));
      ui->sortieList->setItem(elem,1,new QTableWidgetItem(sortie[elem].values));
    }
    for(int ramElem=nbElem;ramElem<nbElem+ramTracked.size();ramElem++){
      ui->sortieList->setItem(ramElem,0,
			      new QTableWidgetItem(QString("Ram : ")+
						   QString::number(ramTracked[ramElem-nbElem])));
      ui->sortieList->setItem(ramElem,1,new QTableWidgetItem(QString("")));
    }
    for(int romElem=nbElem+ramTracked.size();
	romElem<nbElem+ramTracked.size()+romTracked.size();
	romElem++){
      ui->sortieList->setItem(romElem,0,
			      new QTableWidgetItem(QString("Rom : ")+
						   QString::number(romTracked[romElem-nbElem-ramTracked.size()])));
      ui->sortieList->setItem(romElem,1,new QTableWidgetItem(QString("")));
    }
    ui->entreeList->setColumnCount(2);
    ui->entreeList->setRowCount(nbEntrees);
    ui->entreeList->setHorizontalHeaderItem(0,new QTableWidgetItem("Variable"));
    ui->entreeList->setHorizontalHeaderItem(1,new QTableWidgetItem("Valeur"));
    for(int elem=0;elem<nbEntrees;elem++){
      int lig=correspondance[entree[elem].nom.toStdString()];
      ui->entreeList->setItem(lig,0,new QTableWidgetItem(entree[elem].nom));
      ui->entreeList->setItem(lig,1,new QTableWidgetItem(entree[elem].values));
    }

    ui->tempsReel->setEnabled(true);
    ui->fastest->setEnabled(true);
    going=false;
    goingFast=false;

}

void MainWindow::doStep(){

  vector<bool> curEntree;
  int taille=1;
  if(valEntree.size()>0){
    taille=valEntree[0].size();
    for(int i=0;i<(int)valEntree.size();i++)
      curEntree.push_back(valEntree[i][curStep%taille]);
  }
  vector<int> orderedRamRomValues;
  NextStep(vars,curEntree,correspondance,ramTracked,romTracked,orderedRamRomValues);
  int nbElem=0;
  for(int var=0;var<(int)vars.size();var++){
    if(vars[var].affichage != nothing && vars[var].fun != IN){
      sortie[nbElem].add(vars[var].valeur);
      ui->sortieList->setItem(nbElem,1,new QTableWidgetItem(sortie[nbElem].values));
      nbElem++;
    }
    else if(vars[var].fun == IN){
      int nbEntrees=correspondance[vars[var].name];
      entree[nbEntrees].add(curEntree[nbEntrees]);
      ui->entreeList->setItem(nbEntrees,1,new QTableWidgetItem(entree[nbEntrees].values));
	
    }
  }
  for(int i=0;i<orderedRamRomValues.size();i++)
    ui->sortieList->setItem(nbElem+i,1,new QTableWidgetItem(QString::number(orderedRamRomValues[i])));
    
    
  if(time.elapsed()-last>1000){
    double temps=time.elapsed()-last;
    temps/=1000;
    ui->nbReelOp->setText(QString::number(nbOp/temps,'g',6));
    last=time.elapsed();
    nbOp=0;
  }
  nbOp++;
  curStep++;

}


void MainWindow::on_fastest_clicked(){
  if(!going){
    clock.setInterval(0.000001);
    clock.start();
    ui->tempsReel->setText("Pause");
    ui->fastest->setText("Pause");
    going=true;
    if(first){
      updateTime();
      time.start();
    }
    first=false;
  }
  else{
    going=false;
    clock.stop();
    ui->tempsReel->setText("Temps Reel");
    ui->fastest->setText("Vitesse Max");
  }
}

void MainWindow::on_tempsReel_clicked()
{
    double val=double(ui->freq->value());
    if(!going && val!=0){
        clock.setInterval(1000./val);
        clock.start();
        ui->tempsReel->setText("Pause");
	ui->fastest->setText("Pause");
        going=true;
	if(first){
	  updateTime();
	  time.start();
	}
	first=false;
    }
    else{
        going=false;
        clock.stop();
        ui->tempsReel->setText("Temps Reel");
	ui->fastest->setText("Vitesse Max");
    }
}

void MainWindow::on_freq_valueChanged(int arg1)
{
    double val=double(arg1);
    if(val!=0)
        clock.setInterval(1000./val);
}

